package com.boot.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.boot.common.constant.GlobalVar;
import com.boot.common.constant.RedisConstant;
import com.boot.common.result.Result;
import com.boot.system.entity.SysMenu;
import com.boot.system.entity.SysUser;
import com.boot.system.mapper.MenuMapper;
import com.boot.system.service.MenuService;
import com.boot.util.CommUtil;
import com.boot.util.ConvertUtil;
import com.boot.util.RedisUtil;
import com.boot.util.SecurityUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, SysMenu> implements MenuService {

    private final RedisUtil redisUtil;

    /**
     * 系统启动完成后，加载菜单列表缓存
     */
    @PostConstruct
    public void initMenu() {
        QueryWrapper query = QueryWrapper.create().from(SysMenu.class);
        query.eq("status", 1);
        List<SysMenu> list = this.list(query);
        for (SysMenu sysMenu : list) {
            String key = StrUtil.format(RedisConstant.Menu.INFO, sysMenu.getId());
            redisUtil.set(key, sysMenu);
        }
        log.info("菜单列表加载完成！");
    }

    @Override
    public List<SysMenu> getMenuTree() {
        // 当前登录用户
        SysUser loginUser = SecurityUtil.getUserInfo();
        // 菜单列表
        List<SysMenu> list = this.getCacheList();
        // 排序
        list.sort(Comparator.comparingInt(SysMenu::getSort).reversed());
        if (!"super".equals(loginUser.getUsername())) {
            // 过滤已禁用和角色
            list = list.stream().filter(item -> item.getStatus().equals(1) && CommUtil.compareArrays(item.getRoleArr(), loginUser.getRoleArr())).toList();
        }
        return ConvertUtil.listToTree(list, "id", "pid", "children", 0L);
    }

    @Override
    public List<SysMenu> getMenuList(Map<String, Object> queryParam) {
        // 当前登录用户
        SysUser loginUser = SecurityUtil.getUserInfo();
        // 查询条件
        QueryWrapper query = QueryWrapper.create().from(SysMenu.class);
        query.and(q -> q.and(SysMenu::getName).like(queryParam.get("keywords")),
                queryParam.get("keywords") != null);
        if (queryParam.get("status") != null) {
            // 状态
            query.eq("status", queryParam.get("status"));
        }
        if (queryParam.get("roles") != null) {
            // 角色
            List<Object> roles = ConvertUtil.objectToList(queryParam.get("roles"));
            if (!roles.isEmpty()) {
                query.and(q -> {
                    for (Object role : roles) {
                        q.or(SysMenu::getRoles).like(role);
                    }
                });
            }
        }
        query.orderBy("sort desc", "id desc");
        List<SysMenu> list = this.list(query);
        if (!list.isEmpty()) {
            List<SysMenu> listTemp = ConvertUtil.listToTree(list, "id", "pid", "children", 0L);
            if (!"super".equals(loginUser.getUsername())) {
                // 过滤系统设计菜单、演示功能菜单
                listTemp = listTemp.stream().filter(item -> !item.getName().startsWith("系统设计") && !item.getName().startsWith("演示功能")).toList();
            }
            return listTemp;
        }
        return List.of();
    }

    @Override
    public Result<?> addMenu(Map<String, Object> dataParam) {
        SysMenu sysMenu = ConvertUtil.mapToClass(dataParam, SysMenu.class);
        sysMenu.setCreateBy(SecurityUtil.getUid());
        sysMenu.setCreateTime(GlobalVar.systemTime);
        sysMenu.setUpdateBy(SecurityUtil.getUid());
        sysMenu.setUpdateTime(GlobalVar.systemTime);
        boolean result = this.save(sysMenu);
        if (result) {
            //更新缓存
            this.setCache(sysMenu.getId());
        } else {
            return Result.error();
        }
        return Result.success(sysMenu);
    }

    @Override
    public Result<?> updateMenu(Map<String, Object> dataParam) {
        SysMenu sysMenu = ConvertUtil.mapToClass(dataParam, SysMenu.class);
        sysMenu.setUpdateBy(SecurityUtil.getUid());
        sysMenu.setUpdateTime(GlobalVar.systemTime);
        boolean result = this.updateById(sysMenu);
        if (result) {
            //更新缓存
            this.deleteCache(Collections.singletonList(sysMenu.getId()));
            this.setCache(sysMenu.getId());
        } else {
            return Result.error();
        }
        return Result.success(sysMenu);
    }

    @Override
    public boolean deleteMenu(Long id) {
        List<Long> idList = new ArrayList<>();
        idList.add(id);
        this.recursiveQuery(id, 2, idList);
        //先删除缓存
        this.deleteCache(idList);
        //数据库-逻辑删除
        this.removeByIds(idList);
        return true;
    }

    @Override
    public void recursiveQuery(Long pid, int type, List<Long> list) {
        if (type == 1) {
            //向上递归查询
            SysMenu sysMenu = this.getById(pid);
            if (sysMenu != null) {
                //添加到列表
                list.add(sysMenu.getId());
                //递归查询
                if (sysMenu.getPid() != null && sysMenu.getPid() > 0) {
                    recursiveQuery(sysMenu.getPid(), type, list);
                }
            }
        } else if (type == 2) {
            //向下递归查询
            QueryWrapper query = QueryWrapper.create().from(SysMenu.class);
            query.eq("pid", pid);
            List<SysMenu> sysMenuList = this.list(query);
            for (SysMenu sysMenu : sysMenuList) {
                list.add(sysMenu.getId());
                //递归查询
                recursiveQuery(sysMenu.getId(), type, list);
            }
        }
    }

    @Override
    public boolean setRole(Map<String, Object> dataParam) {
        String ids = dataParam.get("ids").toString();
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        String roles = dataParam.get("roles").toString();
        return this.update(new SysMenu().setRoles(roles), new QueryWrapper().in("id", idList));
    }

    @Override
    public List<SysMenu> getCacheList() {
        List<SysMenu> list = new ArrayList<>();
        String prefix = StrUtil.format(RedisConstant.Menu.INFO, "*");
        Set<String> keys = redisUtil.getKeys(prefix);
        for (String key : keys) {
            SysMenu sysMenu = (SysMenu) redisUtil.get(key);
            list.add(sysMenu);
        }
        return list;
    }

    @Override
    public SysMenu getCache(Long id) {
        String prefix = StrUtil.format(RedisConstant.Menu.INFO, id);
        //获取真实的缓存Key
        String key = null;
        Set<String> keys = redisUtil.getKeys(prefix);
        for (String item : keys) {
            key = item;
        }
        if (key != null) {
            return (SysMenu) redisUtil.get(key);
        }
        return null;
    }

    @Override
    public void setCache(Long id) {
        SysMenu sysMenu = this.getById(id);
        if (sysMenu != null) {
            String key = StrUtil.format(RedisConstant.Menu.INFO, sysMenu.getId());
            redisUtil.set(key, sysMenu);
        }
    }

    @Override
    public void deleteCache(List<Long> ids) {
        for (Long id : ids) {
            String prefix = StrUtil.format(RedisConstant.Menu.INFO, id, "*");
            //获取真实的缓存Key
            String key = null;
            Set<String> keys = redisUtil.getKeys(prefix);
            for (String item : keys) {
                key = item;
            }
            if (key != null) {
                //删除
                redisUtil.delete(key);
            }
        }
    }
}
